/*
Copyright © 2022 NAME HERE <huangxinbo@aliyun.com>

*/
package cmd

import (
	"fmt"
	"log"
	"migrate/app"
	"migrate/app/db"
	"migrate/app/migrate"
	"migrate/helper"
	"sort"
	"strings"

	"github.com/spf13/cobra"
)

// downCmd represents the down command
var downCmd = &cobra.Command{
	Use:   "down",
	Short: "run down migrations",
	Run: func(cmd *cobra.Command, args []string) {
		migrationVersionStrs, err := cmd.Flags().GetString("migration")
		if err != nil {
			log.Fatalf("up error: %v", err)
		}
		filePath, _ := cmd.Flags().GetString("config")
		app.Setting(&Config, filePath)
		dbCtx := db.Db{
			Config: &Config,
		}
		err = dbCtx.NewDb()
		if err != nil {
			fmt.Printf("init db failed: %v\n", err)
			return
		}
		defer dbCtx.Close()
		dbCtx.Db.Exec("use " + Config.DbName)

		// get all versions
		versions := []string{}
		for _, v := range migrate.Migrations {
			versions = append(versions, v.Version)
		}

		if migrationVersionStrs != "" {
			migrationVersions := strings.Split(migrationVersionStrs, ",")
			for _, v := range migrationVersions {
				if helper.ElementExsit(versions, v) {
					migrate.Versions = append(migrate.Versions, migrationVersions...)
				} else {
					fmt.Printf("version: %s, err: %s\n", v, "version non-existent in --config")
				}
			}
			migrate.Versions = append(migrate.Versions, migrationVersions...)
			// versions order by desc
			sort.Sort(sort.Reverse(sort.StringSlice(migrate.Versions)))
		} else {
			fmt.Println("Please input migration versions, eg: m_20220526085705_create_users,m_20220526134559_create_tests")
			return
		}

		for _, v := range migrate.Migrations {
			if helper.ElementExsit(migrate.Versions, v.Version) {
				migration := db.Migration{}
				dbCtx.Db.Where("version = ?", v.Version).Find(&migration)
				if migration.Version != "" {
					err := v.Down(dbCtx.Db)
					if err != nil {
						fmt.Printf("version: %s, err: %v\n", v.Version, err)
					} else {
						dbCtx.Db.Where("version = ?", v.Version).Delete(&db.Migration{})
						fmt.Printf("version: %s, success\n", v.Version)
					}
				} else {
					fmt.Printf("version: %s, err: %s\n", v.Version, "version non-existent in database")
				}
			}
		}
	},
}

func init() {
	rootCmd.AddCommand(downCmd)

	downCmd.Flags().StringP("config", "c", ".migrate.yaml", "config file path")
	downCmd.Flags().StringP("migration", "m", "", "migration down version name")
}
